﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Drawing.Imaging;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;


namespace WindowsFormsApplication1
{
    public class Decaptcher
    {

        private string Uri = "http://poster.decaptcher.com/";

        private string username = "";
        private string password = "";
        private string referer = "";
        private DecaptcherResult lastResult;
        private byte[] lastBmp;
        private bool flag;

        public Decaptcher(string _username, string _password)
        {
            username = _username;
            password = _password;
        }

        public DecaptcherResult GetCaptchaSolved(string FileUrl)
        {
            HttpWebRequest request = ((HttpWebRequest)(WebRequest.Create(FileUrl)));
            request.Method = "GET";
            HttpWebResponse response = ((HttpWebResponse)(request.GetResponse()));
            Stream requestStream = response.GetResponseStream();
            int streamLength = Convert.ToInt32(response.ContentLength);
            byte[] fileData = new byte[] {
                Convert.ToByte(streamLength)};
            requestStream.Read(fileData, 0, streamLength);
            requestStream.Close();
            return GetCaptchaSolved(fileData);
        }

        public DecaptcherResult GetCaptchaSolved(byte[] File)
        {
            HttpWebRequest request = ((HttpWebRequest)(WebRequest.Create(Uri)));
            request.Method = "POST";
            request.KeepAlive = true;

            string boundary = ("-------------------------" + DateTime.Now.Ticks.ToString("x"));
            string header = ("\r\n" + ("--"
                        + (boundary + "\r\n")));
            string footer = ("\r\n" + ("--"
                        + (boundary + "\r\n")));
            request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
            StringBuilder contents = new StringBuilder();
            contents.Append("\r\n");
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"function\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append("picture2");
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"username\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append(username);
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"password\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append(password);
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"pict_to\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append("0");
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"pict_type\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append(referer);
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"pict\"; filename=\"Untitled.jpg\"" + "\r\n"));
            contents.Append(("Content-Type: image/jpeg" + "\r\n"));
            contents.Append("\r\n");
            byte[] BodyBytes = Encoding.UTF8.GetBytes(contents.ToString());
            byte[] footerBytes = Encoding.UTF8.GetBytes(footer);
            request.ContentLength = (BodyBytes.Length
                        + (File.Length + footerBytes.Length));
            Stream requestStream = request.GetRequestStream();
            requestStream.Write(BodyBytes, 0, BodyBytes.Length);
            requestStream.Write(File, 0, File.Length);
            requestStream.Write(footerBytes, 0, footerBytes.Length);
            requestStream.Flush();
            requestStream.Close();
            request.Timeout = 300000;
            string ret = (new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd());
            try
            {
                return new DecaptcherResult(ret.Split('|')[0], ret.Split('|')[1], ret.Split('|')[2], ret.Split('|')[3], ret.Split('|')[4], ret.Split('|')[5]);
            }
            catch
            {
                return null;
            }
        }

        public DecaptcherResult ClaimBad(DecaptcherResult dr)
        {
            HttpWebRequest request = ((HttpWebRequest)(WebRequest.Create(Uri)));
            request.Method = "POST";
            request.KeepAlive = true;
            string boundary = ("-------------------------" + DateTime.Now.Ticks.ToString("x"));
            string header = ("\r\n" + ("--"
                        + (boundary + "\r\n")));
            string footer = ("\r\n" + ("--"
                        + (boundary + "\r\n")));
            request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
            StringBuilder contents = new StringBuilder();
            contents.Append("\r\n");
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"function\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append("picture_bad2");
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"username\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append(username);
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"password\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append(password);
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"major_id\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append(dr.MajorID);
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"minor_id\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append(dr.MinorID);
            byte[] BodyBytes = Encoding.UTF8.GetBytes(contents.ToString());
            byte[] footerBytes = Encoding.UTF8.GetBytes(footer);
            request.ContentLength = (BodyBytes.Length + footerBytes.Length);
            Stream requestStream = request.GetRequestStream();
            requestStream.Write(BodyBytes, 0, BodyBytes.Length);
            requestStream.Write(footerBytes, 0, footerBytes.Length);
            requestStream.Flush();
            requestStream.Close();
            string ret = (new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd());
            return new DecaptcherResult(ret.Split('|')[0], ret.Split('|')[1], ret.Split('|')[2], ret.Split('|')[3], ret.Split('|')[4], ret.Split('|')[5]);
        }

        public string GetBalance()
        {
            HttpWebRequest request = ((HttpWebRequest)(WebRequest.Create(Uri)));
            request.Method = "POST";
            request.KeepAlive = true;
            string boundary = ("-------------------------" + DateTime.Now.Ticks.ToString("x"));
            string header = ("\r\n" + ("--"
                        + (boundary + "\r\n")));
            string footer = ("\r\n" + ("--"
                        + (boundary + "\r\n")));
            request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
            StringBuilder contents = new StringBuilder();
            contents.Append("\r\n");
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"function\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append("balance");
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"username\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append(username);
            contents.Append(header);
            contents.Append(("Content-Disposition: form-data; name=\"password\"" + "\r\n"));
            contents.Append("\r\n");
            contents.Append(password);
            byte[] BodyBytes = Encoding.UTF8.GetBytes(contents.ToString());
            byte[] footerBytes = Encoding.UTF8.GetBytes(footer);
            request.ContentLength = (BodyBytes.Length + footerBytes.Length);
            Stream requestStream = request.GetRequestStream();
            requestStream.Write(BodyBytes, 0, BodyBytes.Length);
            requestStream.Write(footerBytes, 0, footerBytes.Length);
            requestStream.Flush();
            requestStream.Close();
            string ret = (new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd());
            return ret;
        }

        /*protected override void Finalize() {
        
        }*/

        private byte[] BmpToBytes(Bitmap bmp)
        {
            MemoryStream m = new MemoryStream();
            bmp.Save(m, ImageFormat.Jpeg);

            byte[] output = m.GetBuffer();
            bmp.Dispose();
            m.Close();

            return output;
        }

        internal DecaptcherResult GetCaptchaSolved(Bitmap captchaBmp)
        {
            lastBmp = BmpToBytes(captchaBmp);

            flag = false;
            Thread n = new Thread(new ThreadStart(GetCaptchaSolvedThread));
            n.Start();

            while (!flag)
            {
                Application.DoEvents();
            }

            return lastResult;
        }

        private void GetCaptchaSolvedThread()
        {
            lastResult = GetCaptchaSolved(lastBmp);
            flag = true;
        }
    }

    public class DecaptcherResult
    {
        private string _ResultCode, _MajorID, _MinorID, _Type, _Timeout, _Text;

        public DecaptcherResult(string resultCode, string majorID, string minorID, string type, string timeout, string text)
        {
            this._ResultCode = resultCode;
            this._MajorID = majorID;
            this._MinorID = minorID;
            this._Type = type;
            this._Timeout = timeout;
            this._Text = text;
        }

        public string ResultCode
        {
            get
            {
                return _ResultCode;
            }
            set
            {
                _ResultCode = value;
            }
        }

        public string MajorID
        {
            get
            {
                return _MajorID;
            }
            set
            {
                _MajorID = value;
            }
        }

        public string MinorID
        {
            get
            {
                return _MinorID;
            }
            set
            {
                _MinorID = value;
            }
        }

        public string Type
        {
            get
            {
                return _Type;
            }
            set
            {
                _Type = value;
            }
        }

        public string Timeout
        {
            get
            {
                return _Timeout;
            }
            set
            {
                _Timeout = value;
            }
        }

        public string Text
        {
            get
            {
                return _Text;
            }
            set
            {
                _Text = value;
            }
        }
    }
}
